home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Utilities / Programming / EnterAct 3.7.3 / hAWK project / AWK Source / EVAL.C < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-08  |  31.2 KB  |  1,209 lines  |  [TEXT/TOPC]

  1. /*
  2.  * eval.c - gawk parse tree interpreter 
  3.  */
  4.  
  5. /* Copyright © 1986, 1988, 1989 1991 the Free Software Foundation, Inc.
  6.  *         This file is part of GAWK, the GNU implementation of the
  7.  * AWK Progamming Language, modified for the Macintosh (also called hAWK).
  8.  *         GAWK is free software; you can redistribute or modify
  9.  * it under the terms of the GNU General Public License as published by
  10.  * the Free Software Foundation; either version 1, or any later version.
  11.  *         GAWK is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14.  * GNU General Public License for more details.
  15.  *         You should have received a copy of the GNU General Public License
  16.  * along with GAWK; see the file "COPYING hAWK". If not, write to
  17.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  * Modified for THINK C 4 on the Macintosh by Ken Earle (Dynabyte) Aug 1991.
  19.  */
  20.  #include <math.h>
  21. #include "AWK.H"
  22.  
  23. extern void do_print(register NODE *tree);
  24. extern void do_printf(NODE *tree);
  25. extern NODE *do_match(NODE *tree);
  26. extern NODE *do_sub(NODE *tree);
  27. extern NODE *do_getline(NODE *tree);
  28. extern NODE *concat_exp(NODE *tree);
  29. extern short in_array(NODE *symbol, NODE *subs);
  30. extern void do_delete(NODE *symbol, NODE *tree);
  31. /*extern double pow();*/
  32.  
  33. /*EVAL.C*/
  34. short interpret(NODE *tree);
  35. NODE *r_tree_eval(NODE *tree);
  36. void assign_number(NODE **ptr, AWKNUM value);
  37. static short eval_condition(NODE *tree);
  38. short cmp_nodes(NODE *t1, NODE *t2);
  39. static NODE *op_assign(NODE *tree);
  40. static NODE *func_call(NODE *name, NODE *arg_list);
  41. NODE **get_lhs(NODE *ptr, short assign);
  42. static NODE *match_op(NODE *tree);
  43.  
  44. #if 0
  45. /* Work in progress */
  46. void UpdateTIME(void);
  47. #endif
  48.  
  49. NODE *_t;        /* used as a temporary in macros */
  50. #ifdef MSDOS
  51. double _msc51bug;    /* to get around a bug in MSC 5.1 */
  52. #endif
  53. NODE *ret_node;
  54.  
  55. /* More of that debugging stuff */
  56. #ifdef    DEBUG
  57. #define DBG_P(X) print_debug X
  58. #else
  59. #define DBG_P(X)
  60. #endif
  61.  
  62. /* Macros and variables to save and restore function and loop bindings */
  63. /*
  64.  * the val variable allows return/continue/break-out-of-context to be
  65.  * caught and diagnosed
  66.  */
  67. #define PUSH_BINDING(stack, x, val) (memcpy ((char *)(stack), (char *)(x), sizeof (jmp_buf)), val++)
  68. #define RESTORE_BINDING(stack, x, val) (memcpy ((char *)(x), (char *)(stack), sizeof (jmp_buf)), val--)
  69.  
  70. static jmp_buf loop_tag;    /* always the current binding */
  71. static short loop_tag_valid = 0;    /* nonzero when loop_tag valid */
  72. static short func_tag_valid = 0;
  73. static jmp_buf func_tag;
  74. extern short exiting, exit_val;
  75.  
  76. /*
  77.  * This table is used by the regexp routines to do case independant
  78.  * matching. Basically, every ascii character maps to itself, except
  79.  * uppercase letters map to lower case ones. This table has 256
  80.  * entries, which may be overkill. Note also that if the system this
  81.  * is compiled on doesn't use 7-bit ascii, casetable[] should not be
  82.  * defined to the linker, so gawk should not load.
  83.  *
  84.  * Do NOT make this array static, it is used in several spots, not
  85.  * just in this file.
  86.  */
  87. #if 'a' == 97    /* it's ascii */
  88. char casetable[] = {
  89.     '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
  90.     '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
  91.     '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
  92.     '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
  93.     /* ' '     '!'     '"'     '#'     '$'     '%'     '&'     ''' */
  94.     '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
  95.     /* '('     ')'     '*'     '+'     ','     '-'     '.'     '/' */
  96.     '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
  97.     /* '0'     '1'     '2'     '3'     '4'     '5'     '6'     '7' */
  98.     '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
  99.     /* '8'     '9'     ':'     ';'     '<'     '='     '>'     '?' */
  100.     '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
  101.     /* '@'     'A'     'B'     'C'     'D'     'E'     'F'     'G' */
  102.     '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
  103.     /* 'H'     'I'     'J'     'K'     'L'     'M'     'N'     'O' */
  104.     '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
  105.     /* 'P'     'Q'     'R'     'S'     'T'     'U'     'V'     'W' */
  106.     '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
  107.     /* 'X'     'Y'     'Z'     '['     '\'     ']'     '^'     '_' */
  108.     '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
  109.     /* '`'     'a'     'b'     'c'     'd'     'e'     'f'     'g' */
  110.     '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
  111.     /* 'h'     'i'     'j'     'k'     'l'     'm'     'n'     'o' */
  112.     '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
  113.     /* 'p'     'q'     'r'     's'     't'     'u'     'v'     'w' */
  114.     '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
  115.     /* 'x'     'y'     'z'     '{'     '|'     '}'     '~' */
  116.     '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
  117.     '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
  118.     '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
  119.     '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
  120.     '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
  121.     '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
  122.     '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
  123.     '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
  124.     '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
  125.     '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307',
  126.     '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317',
  127.     '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327',
  128.     '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337',
  129.     '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
  130.     '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
  131.     '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
  132.     '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
  133. };
  134. #else
  135. #include "You lose. You will need a translation table for your character set."
  136. #endif
  137.  
  138. /*
  139.  * Tree is a bunch of rules to run. Returns zero if it hit an exit()
  140.  * statement 
  141.  */
  142. static jmp_buf rule_tag;/* tag the rule currently being run, for NEXT
  143.              * and EXIT statements.  It is static because
  144.              * there are no nested rules */
  145. short interpret(NODE *tree)
  146. {
  147.     volatile jmp_buf loop_tag_stack; /* shallow binding stack for loop_tag */
  148.     
  149.     register NODE *t = NULL;/* temporary */
  150.     volatile NODE **lhs;    /* lhs == Left Hand Side for assigns, etc */
  151.     volatile struct search *l;    /* For array_for */
  152.     volatile NODE *stable_tree;
  153.     extern Boolean gConcurrent;
  154.     
  155.     
  156.     if (gConcurrent)
  157.         {
  158.         if (CheckInWithCallingApp())  /* CodeResource_Helper.c */
  159.             JumpOnHAWKError(999);
  160.         }
  161.     else
  162.         CheckForInterrupt();
  163.     
  164.     if (tree == NULL)
  165.         return 1;
  166.     
  167.     sourceline = tree->source_line;
  168.     source = tree->source_file;
  169.     switch (tree->type) {
  170.     case Node_rule_list:
  171.         for (t = tree; t != NULL; t = t->rnode) {
  172.             tree = t->lnode;
  173.         /* FALL THROUGH */
  174.     case Node_rule_node:
  175.             sourceline = tree->source_line;
  176.             source = tree->source_file;
  177.             switch (setjmp(rule_tag)) {
  178.             case 0:    /* normal non-jump */
  179.                 /* test pattern, if any */
  180.                 if (tree->lnode == NULL 
  181.                     || eval_condition(tree->lnode)) {
  182.                     DBG_P(("Found a rule", tree->rnode));
  183.                     if (tree->rnode == NULL) {
  184.                         /*
  185.                          * special case: pattern with
  186.                          * no action is equivalent to
  187.                          * an action of {print}
  188.                          */
  189.                         NODE printnode;
  190.  
  191.                         printnode.type = Node_K_print;
  192.                         printnode.lnode = NULL;
  193.                         printnode.rnode = NULL;
  194.                         do_print(&printnode);
  195.                     } else if (tree->rnode->type == Node_illegal) {
  196.                         /*
  197.                          * An empty statement
  198.                          * (``{ }'') is different
  199.                          * from a missing statement.
  200.                          * A missing statement is
  201.                          * equal to ``{ print }'' as
  202.                          * above, but an empty
  203.                          * statement is as in C, do
  204.                          * nothing.
  205.                          */
  206.                     } else
  207.                         (void) interpret(tree->rnode);
  208.                 }
  209.                 break;
  210.             case TAG_CONTINUE:    /* NEXT statement */
  211.                 return 1;
  212.             case TAG_BREAK:
  213.                 return 0;
  214.             default:
  215.                 cant_happen();
  216.             }
  217.             if (t == NULL)
  218.                 break;
  219.         }
  220.         break;
  221.  
  222.     case Node_statement_list:
  223.         for (t = tree; t != NULL; t = t->rnode) {
  224.             DBG_P(("Statements", t->lnode));
  225.             (void) interpret(t->lnode);
  226.         }
  227.         break;
  228.  
  229.     case Node_K_if:
  230.         DBG_P(("IF", tree->lnode));
  231.         if (eval_condition(tree->lnode)) {
  232.             DBG_P(("True", tree->rnode->lnode));
  233.             (void) interpret(tree->rnode->lnode);
  234.         } else {
  235.             DBG_P(("False", tree->rnode->rnode));
  236.             (void) interpret(tree->rnode->rnode);
  237.         }
  238.         break;
  239.  
  240.     case Node_K_while:
  241.         PUSH_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  242.  
  243.         DBG_P(("WHILE", tree->lnode));
  244.         stable_tree = tree;
  245.         while (eval_condition(stable_tree->lnode)) {
  246.             switch (setjmp(loop_tag)) {
  247.             case 0:    /* normal non-jump */
  248.                 DBG_P(("DO", stable_tree->rnode));
  249.                 (void) interpret(stable_tree->rnode);
  250.                 break;
  251.             case TAG_CONTINUE:    /* continue statement */
  252.                 break;
  253.             case TAG_BREAK:    /* break statement */
  254.                 RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  255.                 return 1;
  256.             default:
  257.                 cant_happen();
  258.             }
  259.         }
  260.         RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  261.         break;
  262.  
  263.     case Node_K_do:
  264.         PUSH_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  265.         stable_tree = tree;
  266.         do {
  267.             switch (setjmp(loop_tag)) {
  268.             case 0:    /* normal non-jump */
  269.                 DBG_P(("DO", stable_tree->rnode));
  270.                 (void) interpret(stable_tree->rnode);
  271.                 break;
  272.             case TAG_CONTINUE:    /* continue statement */
  273.                 break;
  274.             case TAG_BREAK:    /* break statement */
  275.                 RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  276.                 return 1;
  277.             default:
  278.                 cant_happen();
  279.             }
  280.             DBG_P(("WHILE", stable_tree->lnode));
  281.         } while (eval_condition(stable_tree->lnode));
  282.         RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  283.         break;
  284.  
  285.     case Node_K_for:
  286.         PUSH_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  287.         DBG_P(("FOR", tree->forloop->init));
  288.         (void) interpret(tree->forloop->init);
  289.         DBG_P(("FOR.WHILE", tree->forloop->cond));
  290.         stable_tree = tree;
  291.         while (eval_condition(stable_tree->forloop->cond)) {
  292.             switch (setjmp(loop_tag)) {
  293.             case 0:    /* normal non-jump */
  294.                 DBG_P(("FOR.DO", stable_tree->lnode));
  295.                 (void) interpret(stable_tree->lnode);
  296.                 /* fall through */
  297.             case TAG_CONTINUE:    /* continue statement */
  298.                 DBG_P(("FOR.INCR", stable_tree->forloop->incr));
  299.                 (void) interpret(stable_tree->forloop->incr);
  300.                 break;
  301.             case TAG_BREAK:    /* break statement */
  302.                 RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  303.                 return 1;
  304.             default:
  305.                 cant_happen();
  306.             }
  307.         }
  308.         RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  309.         break;
  310.  
  311.     case Node_K_arrayfor:
  312. #define hakvar forloop->init
  313. #define arrvar forloop->incr
  314.         PUSH_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  315.         DBG_P(("AFOR.VAR", tree->hakvar));
  316.         lhs = (volatile NODE **) get_lhs(tree->hakvar, 1);
  317.         t = tree->arrvar;
  318.         if (t->type == Node_param_list)
  319.             t = stack_ptr[t->param_cnt];
  320.         stable_tree = tree;
  321.         for (l = assoc_scan(t); l; l = assoc_next((struct search *)l)) {
  322.             deref = *((NODE **) lhs);
  323.             do_deref();
  324.             *lhs = dupnode(l->retval);
  325.             if (field_num == 0)
  326.                 set_record(fields_arr[0]->stptr,
  327.                     fields_arr[0]->stlen);
  328.             DBG_P(("AFOR.NEXTIS", *lhs));
  329.             switch (setjmp(loop_tag)) {
  330.             case 0:
  331.                 DBG_P(("AFOR.DO", stable_tree->lnode));
  332.                 (void) interpret(stable_tree->lnode);
  333.             case TAG_CONTINUE:
  334.                 break;
  335.  
  336.             case TAG_BREAK:
  337.                 RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  338.                 field_num = -1;
  339.                 return 1;
  340.             default:
  341.                 cant_happen();
  342.             }
  343.         }
  344.         field_num = -1;
  345.         RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  346.         break;
  347.  
  348.     case Node_K_break:
  349.         DBG_P(("BREAK", NULL));
  350.         if (loop_tag_valid == 0)
  351.             fatal("unexpected break");
  352.         longjmp(loop_tag, TAG_BREAK);
  353.         break;
  354.  
  355.     case Node_K_continue:
  356.         DBG_P(("CONTINUE", NULL));
  357.         if (loop_tag_valid == 0)
  358.             fatal("unexpected continue");
  359.         longjmp(loop_tag, TAG_CONTINUE);
  360.         break;
  361.  
  362.     case Node_K_print:
  363.         DBG_P(("PRINT", tree));
  364.         do_print(tree);
  365.         break;
  366.  
  367.     case Node_K_printf:
  368.         DBG_P(("PRINTF", tree));
  369.         do_printf(tree);
  370.         break;
  371.  
  372.     case Node_K_next:
  373.         DBG_P(("NEXT", NULL));
  374.         longjmp(rule_tag, TAG_CONTINUE);
  375.         break;
  376.  
  377.     case Node_K_exit:
  378.         /*
  379.          * In A,K,&W, p. 49, it says that an exit statement "...
  380.          * causes the program to behave as if the end of input had
  381.          * occurred; no more input is read, and the END actions, if
  382.          * any are executed." This implies that the rest of the rules
  383.          * are not done. So we immediately break out of the main loop.
  384.          */
  385.         DBG_P(("EXIT", NULL));
  386.         exiting = 1;
  387.         if (tree) {
  388.             t = tree_eval(tree->lnode);
  389.             exit_val = (short) force_number(t);
  390.         }
  391.         free_temp(t);
  392.         longjmp(rule_tag, TAG_BREAK);
  393.         break;
  394.  
  395.     case Node_K_return:
  396.         DBG_P(("RETURN", NULL));
  397.         t = tree_eval(tree->lnode);
  398.         ret_node = dupnode(t);
  399.         free_temp(t);
  400.         longjmp(func_tag, TAG_RETURN);
  401.         break;
  402.  
  403.     default:
  404.         /*
  405.          * Appears to be an expression statement.  Throw away the
  406.          * value. 
  407.          */
  408.         DBG_P(("E", NULL));
  409.         t = tree_eval(tree);
  410.         free_temp(t);
  411.         break;
  412.     }
  413.     return 1;
  414. }
  415.  
  416. /* evaluate a subtree, allocating strings on a temporary stack. */
  417.  
  418. NODE *r_tree_eval(NODE *tree)
  419. {
  420.     register NODE *r, *t1, *t2;    /* return value & temporary subtrees */
  421.     short i;
  422.     register NODE **lhs;
  423.     short di;
  424.     AWKNUM x, x2;
  425.     long lx;
  426.     extern NODE **fields_arr;
  427.  
  428.     source = tree->source_file;
  429.     sourceline = tree->source_line;
  430.     switch (tree->type) {
  431.     case Node_and:
  432.         DBG_P(("AND", tree));
  433.         return tmp_number((AWKNUM) (eval_condition(tree->lnode)
  434.                         && eval_condition(tree->rnode)));
  435.  
  436.     case Node_or:
  437.         DBG_P(("OR", tree));
  438.         return tmp_number((AWKNUM) (eval_condition(tree->lnode)
  439.                         || eval_condition(tree->rnode)));
  440.  
  441.     case Node_not:
  442.         DBG_P(("NOT", tree));
  443.         return tmp_number((AWKNUM) ! eval_condition(tree->lnode));
  444.  
  445.         /* Builtins */
  446.     case Node_builtin:
  447.         DBG_P(("builtin", tree));
  448.         return ((*tree->proc) (tree->subnode));
  449.  
  450.     case Node_K_getline:
  451.         DBG_P(("GETLINE", tree));
  452.         return (do_getline(tree));
  453.  
  454.     case Node_in_array:
  455.         DBG_P(("IN_ARRAY", tree));
  456.         return tmp_number((AWKNUM) in_array(tree->lnode, tree->rnode));
  457.  
  458.     case Node_func_call:
  459.         DBG_P(("func_call", tree));
  460.         return func_call(tree->rnode, tree->lnode);
  461.  
  462.     case Node_K_delete:
  463.         DBG_P(("DELETE", tree));
  464.         do_delete(tree->lnode, tree->rnode);
  465.         return Nnull_string;
  466.  
  467.         /* unary operations */
  468.  
  469.     case Node_var:
  470.     case Node_var_array:
  471.     case Node_param_list:
  472.     case Node_subscript:
  473.     case Node_field_spec:
  474.         DBG_P(("var_type ref", tree));
  475.         lhs = get_lhs(tree, 0);
  476.         field_num = -1;
  477.         deref = 0;
  478.         return *lhs;
  479.  
  480.     case Node_unary_minus:
  481.         DBG_P(("UMINUS", tree));
  482.         t1 = tree_eval(tree->subnode);
  483.         x = -force_number(t1);
  484.         free_temp(t1);
  485.         return tmp_number(x);
  486.  
  487.     case Node_cond_exp:
  488.         DBG_P(("?:", tree));
  489.         if (eval_condition(tree->lnode)) {
  490.             DBG_P(("True", tree->rnode->lnode));
  491.             return tree_eval(tree->rnode->lnode);
  492.         }
  493.         DBG_P(("False", tree->rnode->rnode));
  494.         return tree_eval(tree->rnode->rnode);
  495.  
  496.     case Node_match:
  497.     case Node_nomatch:
  498.     case Node_regex:
  499.         DBG_P(("[no]match_op", tree));
  500.         return match_op(tree);
  501.  
  502.     case Node_func:
  503.         fatal("function `%s' called with space between name and (,\n%s",
  504.             tree->lnode->param,
  505.             "or used in other expression context");
  506.  
  507.     /* assignments */
  508.     case Node_assign:
  509.         DBG_P(("ASSIGN", tree));
  510.         r = tree_eval(tree->rnode);
  511.         lhs = get_lhs(tree->lnode, 1);
  512.         *lhs = dupnode(r);
  513.         free_temp(r);
  514.         do_deref();
  515.         if (field_num == 0)
  516.             set_record(fields_arr[0]->stptr, fields_arr[0]->stlen);
  517.         field_num = -1;
  518.         return *lhs;
  519.  
  520.     /* other assignment types are easier because they are numeric */
  521.     case Node_preincrement:
  522.     case Node_predecrement:
  523.     case Node_postincrement:
  524.     case Node_postdecrement:
  525.     case Node_assign_exp:
  526.     case Node_assign_times:
  527.     case Node_assign_quotient:
  528.     case Node_assign_mod:
  529.     case Node_assign_plus:
  530.     case Node_assign_minus:
  531.         return op_assign(tree);
  532.     default:
  533.         break;    /* handled below */
  534.     }
  535.  
  536.     /* evaluate subtrees in order to do binary operation, then keep going */
  537.     t1 = tree_eval(tree->lnode);
  538.     t2 = tree_eval(tree->rnode);
  539.  
  540.     switch (tree->type) {
  541.     case Node_concat:
  542.         DBG_P(("CONCAT", tree));
  543.         t1 = force_string(t1);
  544.         t2 = force_string(t2);
  545.  
  546.         r = newnode(Node_val);
  547.         r->flags |= (STR|TEMP);
  548.         r->stlen = t1->stlen + t2->stlen;
  549.         r->stref = 1;
  550.         emalloc(r->stptr, char *, r->stlen + 1, "tree_eval");
  551.         memcpy(r->stptr, t1->stptr, t1->stlen);
  552.         memcpy(r->stptr + t1->stlen, t2->stptr, t2->stlen + 1);
  553.         free_temp(t1);
  554.         free_temp(t2);
  555.         return r;
  556.  
  557.     case Node_geq:
  558.     case Node_leq:
  559.     case Node_greater:
  560.     case Node_less:
  561.     case Node_notequal:
  562.     case Node_equal:
  563.         di = cmp_nodes(t1, t2);
  564.         free_temp(t1);
  565.         free_temp(t2);
  566.         switch (tree->type) {
  567.         case Node_equal:
  568.             DBG_P(("EQUAL", tree));
  569.             return tmp_number((AWKNUM) (di == 0));
  570.         case Node_notequal:
  571.             DBG_P(("NOT_EQUAL", tree));
  572.             return tmp_number((AWKNUM) (di != 0));
  573.         case Node_less:
  574.             DBG_P(("LESS_THAN", tree));
  575.             return tmp_number((AWKNUM) (di < 0));
  576.         case Node_greater:
  577.             DBG_P(("GREATER_THAN", tree));
  578.             return tmp_number((AWKNUM) (di > 0));
  579.         case Node_leq:
  580.             DBG_P(("LESS_THAN_EQUAL", tree));
  581.             return tmp_number((AWKNUM) (di <= 0));
  582.         case Node_geq:
  583.             DBG_P(("GREATER_THAN_EQUAL", tree));
  584.             return tmp_number((AWKNUM) (di >= 0));
  585.         default:
  586.             cant_happen();
  587.         }
  588.         break;
  589.     default:
  590.         break;    /* handled below */
  591.     }
  592.  
  593.     (void) force_number(t1);
  594.     (void) force_number(t2);
  595.  
  596.     switch (tree->type) {
  597.     case Node_exp:
  598.         DBG_P(("EXPONENT", tree));
  599.         if ((lx = t2->numbr) == t2->numbr) {    /* integer exponent */
  600.             if (lx == 0)
  601.                 x = 1;
  602.             else if (lx == 1)
  603.                 x = t1->numbr;
  604.             else {
  605.                 /* doing it this way should be more precise */
  606.                 for (x = x2 = t1->numbr; --lx; )
  607.                     x *= x2;
  608.             }
  609.         } else
  610.             x = pow((double) t1->numbr, (double) t2->numbr);
  611.         free_temp(t1);
  612.         free_temp(t2);
  613.         return tmp_number(x);
  614.  
  615.     case Node_times:
  616.         DBG_P(("MULT", tree));
  617.         x = t1->numbr * t2->numbr;
  618.         free_temp(t1);
  619.         free_temp(t2);
  620.         return tmp_number(x);
  621.  
  622.     case Node_quotient:
  623.         DBG_P(("DIVIDE", tree));
  624.         x = t2->numbr;
  625.         free_temp(t2);
  626.         if (x == (AWKNUM) 0)
  627.             fatal("division by zero attempted");
  628.             /* NOTREACHED */
  629.         else {
  630.             x = t1->numbr / x;
  631.             free_temp(t1);
  632.             return tmp_number(x);
  633.         }
  634.  
  635.     case Node_mod:
  636.         DBG_P(("MODULUS", tree));
  637.         x = t2->numbr;
  638.         free_temp(t2);
  639.         if (x == (AWKNUM) 0)
  640.             fatal("division by zero attempted in mod");
  641.             /* NOTREACHED */
  642.         lx = t1->numbr / x;    /* assignment to long truncates */
  643.         x2 = lx * x;
  644.         x = t1->numbr - x2;
  645.         free_temp(t1);
  646.         return tmp_number(x);
  647.  
  648.     case Node_plus:
  649.         DBG_P(("PLUS", tree));
  650.         x = t1->numbr + t2->numbr;
  651.         free_temp(t1);
  652.         free_temp(t2);
  653.         return tmp_number(x);
  654.  
  655.     case Node_minus:
  656.         DBG_P(("MINUS", tree));
  657.         x = t1->numbr - t2->numbr;
  658.         free_temp(t1);
  659.         free_temp(t2);
  660.         return tmp_number(x);
  661.  
  662.     default:
  663.         fatal("illegal type (%d) in tree_eval", tree->type);
  664.     }
  665.     return 0;
  666. }
  667.  
  668. /*
  669.  * This makes numeric operations slightly more efficient. Just change the
  670.  * value of a numeric node, if possible 
  671.  */
  672. void assign_number(NODE **ptr, AWKNUM value)
  673. {
  674.     extern NODE *deref;
  675.     register NODE *n = *ptr;
  676.  
  677. #ifdef DEBUG
  678.     if (n->type != Node_val)
  679.         cant_happen();
  680. #endif
  681.     if (n == Nnull_string) {
  682.         *ptr = make_number(value);
  683.         deref = 0;
  684.         return;
  685.     }
  686.     if (n->stref > 1) {
  687.         *ptr = make_number(value);
  688.         return;
  689.     }
  690.     if ((n->flags & STR) && (n->flags & (MALLOC|TEMP)))
  691.         free(n->stptr);
  692.     n->numbr = value;
  693.     n->flags |= (NUM|NUMERIC);
  694.     n->flags &= ~STR;
  695.     n->stref = 0;
  696.     deref = 0;
  697. }
  698.  
  699.  
  700. /* Is TREE true or false?  Returns 0==false, non-zero==true */
  701. static short eval_condition(NODE *tree)
  702. {
  703.     register NODE *t1;
  704.     short ret;
  705.  
  706.     if (tree == NULL)    /* Null trees are the easiest kinds */
  707.         return 1;
  708.     if (tree->type == Node_line_range) {
  709.         /*
  710.          * Node_line_range is kind of like Node_match, EXCEPT: the
  711.          * lnode field (more properly, the condpair field) is a node
  712.          * of a Node_cond_pair; whether we evaluate the lnode of that
  713.          * node or the rnode depends on the triggered word.  More
  714.          * precisely:  if we are not yet triggered, we tree_eval the
  715.          * lnode; if that returns true, we set the triggered word. 
  716.          * If we are triggered (not ELSE IF, note), we tree_eval the
  717.          * rnode, clear triggered if it succeeds, and perform our
  718.          * action (regardless of success or failure).  We want to be
  719.          * able to begin and end on a single input record, so this
  720.          * isn't an ELSE IF, as noted above.
  721.          */
  722.         if (!tree->triggered)
  723.             if (!eval_condition(tree->condpair->lnode))
  724.                 return 0;
  725.             else
  726.                 tree->triggered = 1;
  727.         /* Else we are triggered */
  728.         if (eval_condition(tree->condpair->rnode))
  729.             tree->triggered = 0;
  730.         return 1;
  731.     }
  732.  
  733.     /*
  734.      * Could just be J.random expression. in which case, null and 0 are
  735.      * false, anything else is true 
  736.      */
  737.  
  738.     t1 = tree_eval(tree);
  739.     if (t1->flags & NUMERIC)
  740.         ret = t1->numbr != 0.0;
  741.     else
  742.         ret = t1->stlen != 0;
  743.     free_temp(t1);
  744.     return ret;
  745. }
  746.  
  747. short cmp_nodes(NODE *t1, NODE *t2)
  748. {
  749.     AWKNUM d;
  750.     AWKNUM d1;
  751.     AWKNUM d2;
  752.     short ret;
  753.     short len1, len2;
  754.  
  755.     if (t1 == t2)
  756.         return 0;
  757.     d1 = force_number(t1);
  758.     d2 = force_number(t2);
  759.     if ((t1->flags & NUMERIC) && (t2->flags & NUMERIC)) {
  760.         d = d1 - d2;
  761.         if (d == 0.0)    /* from profiling, this is most common */
  762.             return 0;
  763.         if (d > 0.0)
  764.             return 1;
  765.         return -1;
  766.     }
  767.     t1 = force_string(t1);
  768.     t2 = force_string(t2);
  769.     len1 = t1->stlen;
  770.     len2 = t2->stlen;
  771.     if (len1 == 0) {
  772.         if (len2 == 0)
  773.             return 0;
  774.         else
  775.             return -1;
  776.     } else if (len2 == 0)
  777.         return 1;
  778.     ret = memcmp(t1->stptr, t2->stptr, len1 <= len2 ? len1 : len2);
  779.     if (ret == 0 && len1 != len2)
  780.         return len1 < len2 ? -1: 1;
  781.     return ret;
  782. }
  783.  
  784. static NODE *op_assign(NODE *tree)
  785. {
  786.     AWKNUM rval, lval;
  787.     NODE **lhs;
  788.     AWKNUM t1, t2;
  789.     long ltemp;
  790.     NODE *tmp;
  791.  
  792.     lhs = get_lhs(tree->lnode, 1);
  793.     lval = force_number(*lhs);
  794.  
  795.     switch(tree->type) {
  796.     case Node_preincrement:
  797.     case Node_predecrement:
  798.         DBG_P(("+-X", tree));
  799.         assign_number(lhs,
  800.             lval + (tree->type == Node_preincrement ? 1.0 : -1.0));
  801.         do_deref();
  802.         if (field_num == 0)
  803.             set_record(fields_arr[0]->stptr, fields_arr[0]->stlen);
  804.         field_num = -1;
  805.         return *lhs;
  806.  
  807.     case Node_postincrement:
  808.     case Node_postdecrement:
  809.         DBG_P(("X+-", tree));
  810.         assign_number(lhs,
  811.             lval + (tree->type == Node_postincrement ? 1.0 : -1.0));
  812.         do_deref();
  813.         if (field_num == 0)
  814.             set_record(fields_arr[0]->stptr, fields_arr[0]->stlen);
  815.         field_num = -1;
  816.         return tmp_number(lval);
  817.     default:
  818.         break;    /* handled below */
  819.     }
  820.  
  821.     tmp = tree_eval(tree->rnode);
  822.     rval = force_number(tmp);
  823.     free_temp(tmp);
  824.     switch(tree->type) {
  825.     case Node_assign_exp:
  826.         DBG_P(("ASSIGN_exp", tree));
  827.         if ((ltemp = rval) == rval) {    /* integer exponent */
  828.             if (ltemp == 0)
  829.                 assign_number(lhs, (AWKNUM) 1);
  830.             else if (ltemp == 1)
  831.                 assign_number(lhs, lval);
  832.             else {
  833.                 /* doing it this way should be more precise */
  834.                 for (t1 = t2 = lval; --ltemp; )
  835.                     t1 *= t2;
  836.                 assign_number(lhs, t1);
  837.             }
  838.         } else
  839.             assign_number(lhs, (AWKNUM) pow((double) lval, (double) rval));
  840.         break;
  841.  
  842.     case Node_assign_times:
  843.         DBG_P(("ASSIGN_times", tree));
  844.         assign_number(lhs, lval * rval);
  845.         break;
  846.  
  847.     case Node_assign_quotient:
  848.         DBG_P(("ASSIGN_quotient", tree));
  849.         if (rval == (AWKNUM) 0)
  850.             fatal("division by zero attempted in /=");
  851.         assign_number(lhs, lval / rval);
  852.         break;
  853.  
  854.     case Node_assign_mod:
  855.         DBG_P(("ASSIGN_mod", tree));
  856.         if (rval == (AWKNUM) 0)
  857.             fatal("division by zero attempted in %=");
  858.         ltemp = lval / rval;    /* assignment to long truncates */
  859.         t1 = ltemp * rval;
  860.         t2 = lval - t1;
  861.         assign_number(lhs, t2);
  862.         break;
  863.  
  864.     case Node_assign_plus:
  865.         DBG_P(("ASSIGN_plus", tree));
  866.         assign_number(lhs, lval + rval);
  867.         break;
  868.  
  869.     case Node_assign_minus:
  870.         DBG_P(("ASSIGN_minus", tree));
  871.         assign_number(lhs, lval - rval);
  872.         break;
  873.     default:
  874.         cant_happen();
  875.     }
  876.     do_deref();
  877.     if (field_num == 0)
  878.         set_record(fields_arr[0]->stptr, fields_arr[0]->stlen);
  879.     field_num = -1;
  880.     return *lhs;
  881. }
  882.  
  883. NODE **stack_ptr;
  884.  
  885. static NODE *func_call(NODE *name, NODE *arg_list)
  886. /*NODE *name;         name is a Node_val giving function name */
  887. /*NODE *arg_list;         Node_expression_list of calling args. */
  888. {
  889.     register NODE *arg, *argp, *r;
  890.     NODE *n, *f;
  891.     volatile jmp_buf func_tag_stack;
  892.     volatile jmp_buf loop_tag_stack;
  893.     volatile short save_loop_tag_valid = 0;
  894.     volatile NODE **save_stack, *save_ret_node;
  895.     NODE **local_stack, **sp;
  896.     short count;
  897.     extern NODE *ret_node;
  898.  
  899.     /*
  900.      * retrieve function definition node
  901.      */
  902.     f = lookup(variables, name->stptr);
  903.     if (!f || f->type != Node_func)
  904.         fatal("function `%s' not defined", name->stptr);
  905. #ifdef FUNC_TRACE
  906.     fprintf(stderr, "function %s called\n", name->stptr);
  907. #endif
  908.     count = f->lnode->param_cnt;
  909.     emalloc(local_stack, NODE **, count * sizeof(NODE *), "func_call");
  910.     sp = local_stack;
  911.  
  912.     /*
  913.      * for each calling arg. add NODE * on stack
  914.      */
  915.     for (argp = arg_list; count && argp != NULL; argp = argp->rnode) {
  916.         arg = argp->lnode;
  917.         r = newnode(Node_var);
  918.         /*
  919.          * call by reference for arrays; see below also
  920.          */
  921.         if (arg->type == Node_param_list)
  922.             arg = stack_ptr[arg->param_cnt];
  923.         if (arg->type == Node_var_array)
  924.             *r = *arg;
  925.         else {
  926.             n = tree_eval(arg);
  927.             r->lnode = dupnode(n);
  928.             r->rnode = (NODE *) NULL;
  929.             free_temp(n);
  930.           }
  931.         *sp++ = r;
  932.         count--;
  933.     }
  934.     if (argp != NULL)    /* left over calling args. */
  935.         warning(
  936.             "function `%s' called with more arguments than declared",
  937.             name->stptr);
  938.     /*
  939.      * add remaining params. on stack with null value
  940.      */
  941.     while (count-- > 0) {
  942.         r = newnode(Node_var);
  943.         r->lnode = Nnull_string;
  944.         r->rnode = (NODE *) NULL;
  945.         *sp++ = r;
  946.     }
  947.  
  948.     /*
  949.      * Execute function body, saving context, as a return statement
  950.      * will longjmp back here.
  951.      *
  952.      * Have to save and restore the loop_tag stuff so that a return
  953.      * inside a loop in a function body doesn't scrog any loops going
  954.      * on in the main program.  We save the necessary info in variables
  955.      * local to this function so that function nesting works OK.
  956.      * We also only bother to save the loop stuff if we're in a loop
  957.      * when the function is called.
  958.      */
  959.     if (loop_tag_valid) {
  960.         short junk = 0;
  961.  
  962.         save_loop_tag_valid = (volatile short) loop_tag_valid;
  963.         PUSH_BINDING(loop_tag_stack, loop_tag, junk);
  964.         loop_tag_valid = 0;
  965.     }
  966.     save_stack = (volatile NODE **) stack_ptr;
  967.     stack_ptr = local_stack;
  968.     PUSH_BINDING(func_tag_stack, func_tag, func_tag_valid);
  969.     save_ret_node = (volatile NODE *) ret_node;
  970.     ret_node = Nnull_string;    /* default return value */
  971.     if (setjmp(func_tag) == 0)
  972.         (void) interpret(f->rnode);
  973.  
  974.     r = ret_node;
  975.     ret_node = (NODE *) save_ret_node;
  976.     RESTORE_BINDING(func_tag_stack, func_tag, func_tag_valid);
  977.     stack_ptr = (NODE **) save_stack;
  978.  
  979.     /*
  980.      * here, we pop each parameter and check whether
  981.      * it was an array.  If so, and if the arg. passed in was
  982.      * a simple variable, then the value should be copied back.
  983.      * This achieves "call-by-reference" for arrays.
  984.      */
  985.     sp = local_stack;
  986.     count = f->lnode->param_cnt;
  987.     for (argp = arg_list; count > 0 && argp != NULL; argp = argp->rnode) {
  988.         arg = argp->lnode;
  989.         n = *sp++;
  990.         if (arg->type == Node_var && n->type == Node_var_array) {
  991.             arg->var_array = n->var_array;
  992.             arg->type = Node_var_array;
  993.         }
  994.         deref = n->lnode;
  995.         do_deref();
  996.         freenode(n);
  997.         count--;
  998.     }
  999.     while (count-- > 0) {
  1000.         n = *sp++;
  1001.         deref = n->lnode;
  1002.         do_deref();
  1003.         freenode(n);
  1004.     }
  1005.     free((char *) local_stack);
  1006.  
  1007.     /* Restore the loop_tag stuff if necessary. */
  1008.     if (save_loop_tag_valid) {
  1009.         short junk = 0;
  1010.  
  1011.         loop_tag_valid = (short) save_loop_tag_valid;
  1012.         RESTORE_BINDING(loop_tag_stack, loop_tag, junk);
  1013.     }
  1014.  
  1015.     if (!(r->flags & PERM))
  1016.         r->flags |= TEMP;
  1017.     return r;
  1018. }
  1019.  
  1020. /*
  1021.  * This returns a POINTER to a node pointer. get_lhs(ptr) is the current
  1022.  * value of the var, or where to store the var's new value 
  1023.  */
  1024.  
  1025. NODE **get_lhs(NODE *ptr, short assign)
  1026. /*short assign;         this is being called for the LHS of an assign. */
  1027. {
  1028.     register NODE **aptr;
  1029.     NODE *n;
  1030.  
  1031. #ifdef DEBUG
  1032.     if (ptr == NULL)
  1033.         cant_happen();
  1034. #endif
  1035.     deref = NULL;
  1036.     field_num = -1;
  1037.     switch (ptr->type) {
  1038.     case Node_var:
  1039.     case Node_var_array:
  1040.         if (ptr == NF_node && (short) NF_node->var_value->numbr == -1)
  1041.             (void) get_field(HUGE-1, assign); /* parse record */
  1042.         deref = ptr->var_value;
  1043. #ifdef DEBUG
  1044.         if (deref->type != Node_val)
  1045.             cant_happen();
  1046.         if (deref->flags == 0)
  1047.             cant_happen();
  1048. #endif
  1049.         return &(ptr->var_value);
  1050.  
  1051.     case Node_param_list:
  1052.         n = stack_ptr[ptr->param_cnt];
  1053.         deref = n->var_value;
  1054. #ifdef DEBUG
  1055.         if (deref->type != Node_val)
  1056.             cant_happen();
  1057.         if (deref->flags == 0)
  1058.             cant_happen();
  1059. #endif
  1060.         return &(n->var_value);
  1061.  
  1062.     case Node_field_spec:
  1063.         n = tree_eval(ptr->lnode);
  1064.         field_num = (short) force_number(n);
  1065.         free_temp(n);
  1066.         if (field_num < 0)
  1067.             fatal("attempt to access field %d", field_num);
  1068.         aptr = get_field(field_num, assign);
  1069.         deref = *aptr;
  1070.         return aptr;
  1071.  
  1072.     case Node_subscript:
  1073.         n = ptr->lnode;
  1074.         if (n->type == Node_param_list)
  1075.             n = stack_ptr[n->param_cnt];
  1076.         aptr = assoc_lookup(n, concat_exp(ptr->rnode));
  1077.         deref = *aptr;
  1078. #ifdef DEBUG
  1079.         if (deref->type != Node_val)
  1080.             cant_happen();
  1081.         if (deref->flags == 0)
  1082.             cant_happen();
  1083. #endif
  1084.         return aptr;
  1085.     case Node_func:
  1086.         fatal ("`%s' is a function, assignment is not allowed",
  1087.             ptr->lnode->param);
  1088.     default:
  1089.         cant_happen();
  1090.     }
  1091.     return 0;
  1092. }
  1093.  
  1094. static NODE *match_op(NODE *tree)
  1095. {
  1096.     NODE *t1;
  1097.     struct re_pattern_buffer *rp;
  1098.     short i;
  1099.     short match = 1;
  1100.  
  1101.     if (tree->type == Node_nomatch)
  1102.         match = 0;
  1103.     if (tree->type == Node_regex)
  1104.         t1 = WHOLELINE;
  1105.     else {
  1106.         if (tree->lnode)
  1107.             t1 = force_string(tree_eval(tree->lnode));
  1108.         else
  1109.             t1 = WHOLELINE;
  1110.         tree = tree->rnode;
  1111.     }
  1112.     if (tree->type == Node_regex) {
  1113.         rp = tree->rereg;
  1114.         if (/*!strict && */ ((IGNORECASE_node->var_value->numbr != 0)
  1115.             ^ (tree->re_case != 0))) {
  1116.             /* recompile since case sensitivity differs */
  1117.             rp = tree->rereg =
  1118.                 mk_re_parse(tree->re_text,
  1119.                 (IGNORECASE_node->var_value->numbr != 0));
  1120.             tree->re_case =
  1121.                 (IGNORECASE_node->var_value->numbr != 0);
  1122.         }
  1123.     } else {
  1124.         rp = make_regexp(force_string(tree_eval(tree)),
  1125.             (IGNORECASE_node->var_value->numbr != 0));
  1126.         if (rp == NULL)
  1127.             cant_happen();
  1128.     }
  1129.     i = re_search(rp, t1->stptr, t1->stlen, 0, t1->stlen,
  1130.         (struct re_registers *) NULL);
  1131.     i = (i == -1) ^ (match == 1);
  1132.     free_temp(t1);
  1133.     if (tree->type != Node_regex) {
  1134.         free(rp->buffer);
  1135.         free(rp->fastmap);
  1136.         free((char *) rp);
  1137.     }
  1138.     return tmp_number((AWKNUM) i);
  1139. }
  1140.  
  1141. #if 0
  1142. /* Update the TIME variable once per second? Not like this, you don't
  1143. - I'll be back... */
  1144. void UpdateTIME()
  1145.     {
  1146.     long        thisTime;
  1147.     static long    lastTime;
  1148.     time_t        now;
  1149.     struct tm    *date;
  1150.     char        s[30];
  1151.     short            len;
  1152.     extern NODE *TIME_node;
  1153.     
  1154.     Delay(0L, &thisTime);
  1155.     if (thisTime - lastTime < 60L) return;
  1156.     lastTime = thisTime;
  1157.     
  1158.     now = time(NULL);
  1159.     /*now = (time_t)lastTime;*/
  1160.     date = localtime(&now);
  1161.     len = (short)strftime(s,30, "%I:%M:%S %p", date);
  1162.     /*
  1163.     if (TIME_node->stlen < len)
  1164.         len = TIME_node->stlen;
  1165.     */
  1166.     memcpy(TIME_node->stptr, s, len);
  1167.     TIME_node->stptr[len] = '\0';
  1168.     /*
  1169.     strftime(TIME_node->stptr,TIME_node->stlen + 1, "%I:%M:%S %p", date);
  1170.     */
  1171.     }
  1172. #endif
  1173.  
  1174. /* static/global variable (re)init */
  1175. extern void NullOut(char *str, long nBytes);
  1176.  
  1177. void InitEval(void);
  1178.  
  1179. void InitEval()
  1180.     {
  1181.     NullOut((Ptr)loop_tag, sizeof(jmp_buf));
  1182.     loop_tag_valid = 0;    /* nonzero when loop_tag valid */
  1183.     func_tag_valid = 0;
  1184.     NullOut((Ptr)func_tag, sizeof(jmp_buf));
  1185.     /* in interpret: */
  1186.         NullOut((Ptr)rule_tag, sizeof(jmp_buf));
  1187.     }
  1188.  
  1189. void SaveEval(void);
  1190. void RestoreEval(void);
  1191. void SaveEval()
  1192.     {
  1193.     BlockMove((Ptr)loop_tag, (Ptr)(hs->loop_tag), sizeof(jmp_buf));
  1194.     hs->loop_tag_valid = loop_tag_valid;
  1195.     hs->func_tag_valid = func_tag_valid;
  1196.     BlockMove((Ptr)func_tag, (Ptr)(hs->func_tag), sizeof(jmp_buf));
  1197.     BlockMove((Ptr)rule_tag, (Ptr)(hs->rule_tag), sizeof(jmp_buf));
  1198.     }
  1199.  
  1200. void RestoreEval()
  1201.     {
  1202.     BlockMove((Ptr)(hs->loop_tag), (Ptr)loop_tag, sizeof(jmp_buf));
  1203.     loop_tag_valid = hs->loop_tag_valid;
  1204.     func_tag_valid = hs->func_tag_valid;
  1205.     BlockMove((Ptr)(hs->func_tag), (Ptr)func_tag, sizeof(jmp_buf));
  1206.     BlockMove((Ptr)(hs->rule_tag), (Ptr)rule_tag, sizeof(jmp_buf));
  1207.     }
  1208.  
  1209.